
#include "Tank.h"
#include "Bullet.h"
#include "EntityManager.h"
#include "Event.h"
#include "EventSystem.h"
#include "Game.h"
#include "BitmapFont.h"
#include <math.h>
#include "../../SGD Wrappers/CSGD_TextureManager.h"
#include "../../SGD Wrappers/CSGD_DirectInput.h"

//Constructor
Tank::Tank(void)
{
	this->x					= 0.0f;
	this->y					= 0.0f;
	this->velocityX			= 0.0f;
	this->velocityY			= 0.0f;
	this->rotation			= 0.0f;
	this->collisionRadius	= 1.0f;
	this->isAlive			= true;
	this->entityType		= ENTITY_TANK;
	this->velocityX			= 0.0f;
	this->velocityY			= 0.0f;
	this->moveSpeed			= 180.0f;
	this->buildPoints		= 0;
	this->upgradeLevel		= 0;
	this->healthCurrent		= 3;
	this->healthMax			= 3;
	this->attackRange		= 10.0f;
	this->attackTarget		= nullptr;
	this->spawnpointIsEmpty	= false;
	textureID = CSGD_TextureManager::GetInstance()->LoadTexture(_T("../Resource/Graphics/PlaceholderImage.png"));

	//Register for events
	EventSystem::GetInstance()->Register("TESTEVENT", this);
	EventSystem::GetInstance()->Register("SPAWNPOINT_IS_EMPTY", this);
	EventSystem::GetInstance()->Register("ENEMY_HIT_BASE", this);
}


//Destructor
Tank::~Tank(void)
{
	//Unregister for events
	EventSystem::GetInstance()->Unregister("TESTEVENT", this);
	EventSystem::GetInstance()->Unregister("SPAWNPOINT_IS_EMPTY", this);
	EventSystem::GetInstance()->Unregister("ENEMY_HIT_BASE", this);
}


//Update
void Tank::Update(float dt)
{
	CSGD_DirectInput* DI = CSGD_DirectInput::GetInstance();
	EntityManager* entityManager = EntityManager::GetInstance();
	EventSystem* eventSystem = EventSystem::GetInstance();

	//Clear target if it has died
	if (attackTarget != nullptr && attackTarget->isAlive == false)
	{
		attackTarget->RemoveReference();
		attackTarget = nullptr;
	}

	//Clear target if it is out of range
	if (attackTarget != nullptr && 
		sqrt((attackTarget->x - x)*(attackTarget->x - x) + (attackTarget->y - y)*(attackTarget->y - y)))
	{
		attackTarget->RemoveReference();
		attackTarget = nullptr;
	}

	//Search for a target
	if (attackTarget == nullptr)
	{
		//Ask entity manager for a list of entities in range
		//Search list for highest priority target
	}

	//Shoot bullets at the target
	if (attackTarget != nullptr)
	{
		//Create bullet
	}

	//Movement input
	velocityX = 0.0f;
	velocityY = 0.0f;
	if (DI->KeyDown(DIK_LEFT)  || DI->KeyDown(DIK_A)) velocityX = -1.0f;
	if (DI->KeyDown(DIK_RIGHT) || DI->KeyDown(DIK_D)) velocityX =  1.0f;
	if (DI->KeyDown(DIK_UP)    || DI->KeyDown(DIK_W)) velocityY = -1.0f;
	if (DI->KeyDown(DIK_DOWN)  || DI->KeyDown(DIK_S)) velocityY =  1.0f;
	float magnitude = sqrt(velocityX*velocityX + velocityY*velocityY);
	if (magnitude >= 0.1f)
	{
		velocityX /= magnitude;
		velocityY /= magnitude;
		x += velocityX * moveSpeed * dt;
		y += velocityY * moveSpeed * dt;
	}

	//Set rotation
	float newRotation = rotation;
	if (velocityX >=  0.1f) newRotation = 3.141f * 0.5f;
	if (velocityX <= -0.1f) newRotation = 3.141f * 1.5f;
	if (velocityY >=  0.1f) newRotation = 3.141f * 1.0f;
	if (velocityY <= -0.1f) newRotation = 3.141f * 0.01f;
	if (velocityX >=  0.1f && velocityY >=  0.1f) newRotation = 3.141f * 0.75f;
	if (velocityX >=  0.1f && velocityY <= -0.1f) newRotation = 3.141f * 0.25f;
	if (velocityX <= -0.1f && velocityY >=  0.1f) newRotation = 3.141f * 1.25f;
	if (velocityX <= -0.1f && velocityY <= -0.1f) newRotation = 3.141f * 1.75f;
	float rotationRate = 8.0f * dt;
	if (rotation - newRotation < -0.001f)
	{
		if (fabs(rotation - newRotation) > 3.141f) rotation -= rotationRate;
		else rotation += rotationRate;
	}
	if (rotation - newRotation >  0.001f)
	{
		if (fabs(rotation - newRotation) > 3.141f) rotation += rotationRate;
		else rotation -= rotationRate;
	}
	if (rotation >  6.283f) rotation -= 6.281f;
	if (rotation < -0.001f) rotation += 6.281f;

	//Tower placement input
	if (DI->KeyPressed(DIK_E))
	{
		eventSystem->SendEvent("TESTEVENT",nullptr,nullptr,nullptr);
	}

	//Check for victory
	if (spawnpointIsEmpty && healthCurrent > 0)
	{
		//Search for living enemies
		bool livingEnemiesExist = false;
		EntityManager* entityManager = entityManager->GetInstance();
		list<Entity*> entityList = entityManager->FindEntitiesInRange(x, y, 9999);
		list<Entity*>::iterator iterator;
		if (entityList.size() > 0)
		{
			for (iterator = entityList.begin(); iterator != entityList.end(); ++iterator)
			{
				Entity* e = (*iterator);
				if (e->entityType == ENTITY_ENEMY && e->isAlive)
				{
					livingEnemiesExist = true;
					break;
				}
			}
		}
		if (livingEnemiesExist == false)
		{
			eventSystem->SendEvent("WAVE_VICTORY",nullptr,nullptr,nullptr);
		}
	}

	//Check for defeat
	if (healthCurrent <= 0)
	{
		eventSystem->SendEvent("WAVE_DEFEAT",nullptr,nullptr,nullptr);
	}
}


//Render
void Tank::Render()
{
	CSGD_TextureManager* TM = CSGD_TextureManager::GetInstance();
	RECT rect = {0, 0, 64, 64};
	POINT ptCenter = { (rect.right - rect.left) / 2, (rect.bottom - rect.top) / 2 };
	TM->Draw(textureID, (int)x - ptCenter.x, (int)y - ptCenter.y, 1.0f, 1.0f, &rect,
		(float)ptCenter.x, (float)ptCenter.y, rotation, D3DCOLOR_ARGB(255,255,255,255));

	TM->Draw(textureID, (int)x-3, (int)y-3, 0.1f, 0.1f, &rect, 32.0f, 32.0f, rotation, D3DCOLOR_ARGB(255,255,50,50));

	//Draw status text
	CBitmapFont* pFont = Game::GetInstance()->GetFont();
	TOSTRINGSTREAM output;
	output << _T("Health: ") << (int)healthCurrent;
	pFont->Draw(output.str().c_str(), 450, 40, 0.9f, D3DCOLOR_ARGB(255,255,255,255));
}


//Handle event
void Tank::HandleEvent(Event* e)
{
	EntityManager* entityManager = EntityManager::GetInstance();

	//Test event
	if (strcmp(e->GetEventType().c_str(),"TESTEVENT") == 0)
	{
		entityManager->CreateEntity(ENTITY_TOWER, x, y);
	}

	//Spawnpoint is empty
	if (strcmp(e->GetEventType().c_str(),"SPAWNPOINT_IS_EMPTY") == 0)
	{
		spawnpointIsEmpty = true;
	}

	//Enemy hit base
	if (strcmp(e->GetEventType().c_str(),"ENEMY_HIT_BASE") == 0)
	{
		healthCurrent -= 1;
	}
}
